097107 ランダム
 HOME | DIARY | PROFILE 【フォローする】 【ログイン】

The Quiet Sound of Water

The Quiet Sound of Water

XML + Sax(読み込み)

●XML + Sax(読み込み)
Saxを使ってXML形式のデータを読み込む:

SaxはXMLのタグ毎にイベントを発生させて処理を行う仕組みである。
XMLファイルを読み込むパーサーとイベントを処理するハンドラをセットにして使用する。
パーサーはJ2SEの標準クラスを使えばよいが、XMLのタグに応じて処理を行うハンドラのほうは実装する必要がある。
とは言っても雛型となるDefaultHandlerを継承してメソッドをオーバーライドするだけでよい。

読み込むXMLに応じて、データを格納するクラスを変更する仕組みを考えた。
MRHandlerはエラー処理とデータクラスを返すメソッドを実装しただけの継承用クラスである。
XMLのタグからデータを抽出して格納するハンドラをデータクラスごとに実装することになる。

以下サンプル。
まずはXML読み込み用のクラス。

package mr.system.data;

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import mr.system.MRLog;

public class MRXMLReader {
static SAXParserFactory factory;
static SAXParser saxParser;

public MRXMLReader(){
try {
factory = SAXParserFactory.newInstance();
saxParser = factory.newSAXParser();
} catch (SAXException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}

public static MRData ReadXMLFile(MRHandler handler,String filename) {
try {
if (factory == null){
factory = SAXParserFactory.newInstance();
}
if (saxParser == null){
saxParser = factory.newSAXParser();
}
saxParser.parse( new File(filename), handler );
if (handler != null){
MRData d = handler.getData();
return (d);
}else{
return null;
}
} catch (SAXException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return (null);
}
}

こいつはハンドラとファイル名を受け取ってパーサーを呼び出すだけである。
ハンドラはデータ用格納用のクラス(MRData)を返すので、呼び出し元に中継して投げ返すだけ。

次にハンドラのサンプル。

package mr.system.data;

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import mr.system.MRLog;

class MRSystemDataHandler extends MRHandler {
private MRSystemData d = null;
private String CurrentElement;

public MRSystemDataHandler(){
d = MRSystemData.GetInstance();
CurrentElement = "";
}

public MRData getData(){
return ((MRData)d);
}

public void startElement(String uri, String localName, String qName, Attributes alist) {
String wk = "";
String vname = "";
String vvalue = "";
System.out.println(localName + "[" + qName + "]");
if (qName.equals("mr:set") || qName.equals("mr:subset")){
for (int i = 0; i < alist.getLength(); i++) {
wk = alist.getQName(i);
if ("name".equals(wk)){
vname = alist.getValue(i);
}else if ("value".equals(wk)){
vvalue = alist.getValue(i);
}
System.out.println(alist.getQName(i) + " = " + alist.getValue(i));
}
d.SetValue(vname, vvalue);
}
}
}
}

こいつはパーサーからのイベントを処理するだけ。
ここではstartElementイベントしか実装していない。
タグ名に応じてMRDataクラス(を継承しているMRSystemDataクラス)に値をセットしている。
MRSystemDataクラスのSetValueメソッドでは、パラメータ名(name属性)と値(value属性)を受け取り、しかるべきプロパティにセットする仕掛け。

ハンドラクラスとデータクラスを拡張することでいろいろなデータに対応する。
使用時にいちいちハンドラクラスとデータクラスの組み合わせを指定するのがめんどくさい場合は、Factoryクラスのようなのを一匹作ってやればいよい。

package mr.system.data;

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import mr.system.MRLog;

public class MRDataReader {
static MRDataHandler h;
static MRData c;

static public MRSystemData GetSystemData(){
h = new MRSystemDataHandler();
c = MRXMLReader.ReadXMLFile(h, "mrsystem.xml");
return ((MRSystemData)c);
}

static public MRHogeData GetHogeData(){
h = new MRHogeDataHandler();
c = MRXMLReader.ReadXMLFile(h, "mrhoge.xml");
return ((MRHogeData)c);
}
}



© Rakuten Group, Inc.